﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Serialization;
using Curling.CurlingServer;

namespace Curling
{
    [DataContractAttribute]
    public class ReplayManager
    {
        [DataMemberAttribute]
        public StoneReplay[] StonesReplay { get; set; }
        [DataMemberAttribute]
        public List<HitReplay> HitsReplay { get; set; }
        [DataMemberAttribute]
        public List<BroomReplay> BroomReplayFrames { get; set; }
        [DataMemberAttribute]
        public int CurrentHitIndex = 0;
        [DataMemberAttribute]
        public int CurrentBroomIndex = 1;

        [DataMemberAttribute]
        public DateTime BeginTime;
        [DataMemberAttribute]
        public TimeSpan Duration;
        [DataMemberAttribute]
        public TimeSpan CurrentReplayTime;

        [DataMemberAttribute]
        public bool IsPlaying { get; set; }

        [DataMemberAttribute]
        public static bool IsEnabled { get; set; }

        public delegate void ReplayFinishedEventHandler(object sender, EventArgs e);
        public event ReplayFinishedEventHandler ReplayFinished;

        static ReplayManager()
        {
            IsEnabled = true;
        }

        public ReplayManager(List<Stone> Stones)
        {
            BeginTime = DateTime.Now;

            StonesReplay = new StoneReplay[Stones.Count];
            HitsReplay = new List<HitReplay>();
            BroomReplayFrames = new List<BroomReplay>();

            BroomReplayFrames.Add(new BroomReplay() { X = 0, Y = 0, TimeStamp = DateTime.Now.Subtract(BeginTime), Visible = false });

            foreach (Stone stone in Stones)
            {
                StoneReplay stoneReplay = new StoneReplay(stone.stoneEntity);

                StonesReplay[stone.stoneEntity.ID] = stoneReplay;
            }
        }

        public StoneReplayFrame AddFrame(Stone stone, TimeSpan GameTime)
        {
            return StonesReplay[stone.stoneEntity.ID].AddFrame(stone, GameTime);
        }

        public void AddHit(double Impulse, TimeSpan GameTime)
        {
            HitsReplay.Add(new HitReplay() { Impulse = Impulse, TimeStamp = GameTime });
        }

        public void AddBroomFrame(double X, double Y, double Intensity, bool Visible, TimeSpan GameTime)
        {
            BroomReplayFrames.Add(new BroomReplay() { X = X, Y = Y, Intensity = Intensity, TimeStamp = GameTime, Visible = Visible });
        }

        public void StopRecord(TimeSpan Duration)
        {
            this.Duration = Duration;// = DateTime.Now.Subtract(BeginTime);
        }

        public void StartPlay()
        {
            IsPlaying = true;

            BeginTime = DateTime.Now;

            CurrentHitIndex = 0;
            CurrentBroomIndex = 1;
            
            foreach (StoneReplay stoneReplay in StonesReplay)
            {
                if (stoneReplay != null)
                {
                    stoneReplay.CurrentFrame = 1;
                }
            }
        }

        public void StopPlay()
        {
            IsPlaying = false;

            ReplayFinished(this, EventArgs.Empty);
        }

        public void Update(TimeSpan CurrentReplayTime)
        {
            this.CurrentReplayTime = CurrentReplayTime;// DateTime.Now.Subtract(BeginTime);

            for (int i = CurrentHitIndex; i < HitsReplay.Count; i++)
            {
                if (CurrentReplayTime.CompareTo(HitsReplay[i].TimeStamp) > 0)
                {
                    CurrentHitIndex = i + 1;

                    SoundManager.PlayStoneHit(Math.Min(HitsReplay[i].Impulse / 200, 1.0));
                    GameManager.vibrate.Start(TimeSpan.FromMilliseconds(Math.Max(Math.Min(HitsReplay[i].Impulse / 4, 60), 20)));
                }
            }

            if (CurrentReplayTime.CompareTo(Duration) > 0)
            {
                IsPlaying = false;

                ReplayFinished(this, EventArgs.Empty);
            }
        }

        public StoneReplayFrame GetCurrentFrame(Stone stone)
        {
            if (!IsPlaying)
            {
                return null;
            }

            return StonesReplay[stone.stoneEntity.ID].GetFrame(CurrentReplayTime);
        }

        public StoneReplayFrame GetFrame(Stone stone, TimeSpan GameTime)
        {
            return StonesReplay[stone.stoneEntity.ID].GetFrame(GameTime);
        }

        public StoneReplayFrame GetLastFrame(Stone stone)
        {
            return StonesReplay[stone.stoneEntity.ID].GetLastFrame();
        }

        public BroomReplay GetCurrentBroomFrame()
        {
            for (int i = CurrentBroomIndex; i < BroomReplayFrames.Count; i++)
            {
                if (CurrentReplayTime.CompareTo(BroomReplayFrames[i].TimeStamp) < 0)
                {
                    CurrentBroomIndex = i;
                    
                    return BroomReplayFrames[i - 1];
                }
            }

            return BroomReplayFrames[BroomReplayFrames.Count - 1];
        }
    }
}